/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain (a) copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.kizitonwose.calendarview.fraction;

import ohos.aafwk.content.Intent;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.Image;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.Text;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.utils.Color;
import ohos.agp.window.dialog.ToastDialog;
import ohos.agp.window.service.DisplayAttributes;
import ohos.agp.window.service.DisplayManager;

import com.kizitonwose.calendarview.CalendarView;
import com.kizitonwose.calendarview.ResourceTable;
import com.kizitonwose.calendarview.model.CalendarDay;
import com.kizitonwose.calendarview.model.CalendarMonth;
import com.kizitonwose.calendarview.model.enums.DayOwner;
import com.kizitonwose.calendarview.ui.ViewContainer;
import com.kizitonwose.calendarview.uinterface.DayBinder;
import com.kizitonwose.calendarview.uinterface.MonthHeaderFooterBinder;
import com.kizitonwose.calendarview.utils.DayExtensions;
import com.kizitonwose.calendarview.utils.LocalDateExtension;
import com.kizitonwose.calendarview.utils.StringUtils;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.time.format.TextStyle;
import java.util.Locale;

/**
 * @version 1.0
 * @date 2021/2/26/026 15:53
 */
public class Example4Fraction extends BaseFraction {
    private CalendarView exFourCalendar;
    private ComponentContainer legendLayout;
    private LocalDate selectedDate;
    private LocalDate today = LocalDate.now();

    private LocalDate startDate = null;
    private LocalDate endDate = null;
    private DateTimeFormatter headerDateFormatter = DateTimeFormatter.ofPattern("EEE'\n'd MMM");
    private ShapeElement startBackground;
    private ShapeElement endBackground;
    private Text exFourStartDateText;
    private Text exFourEndDateText;
    private Text exFourSaveButton;
    private Image close_fraction;
    private Text clear_selected;
    private float topLeft = 0;
    private float topLeft2 = 0;
    private float topRight = 0;
    private float topRight2 = 0;
    private float bottomRight = 0;
    private float bottomRight2 = 0;
    private float bottomLeft = 0;
    private float bottomLeft2 = 0;

    @Override
    protected int getLayoutResId() {
        return ResourceTable.Layout_example_4_fraction;
    }

    @Override
    protected int getStatusBarColor() {
        return mContext.getColor(ResourceTable.Color_write);
    }

    @Override
    protected void initComponent(Component content, ComponentContainer container, Intent intent) {
        startDate = null;
        endDate = null;
        startBackground = new ShapeElement(mContext, ResourceTable.Graphic_example_4_continuous_selected_bg_start);
        endBackground = new ShapeElement(mContext, ResourceTable.Graphic_example_4_continuous_selected_bg_end);
        exFourCalendar = findComponentById(ResourceTable.Id_exFourCalendar);
        exFourStartDateText = findComponentById(ResourceTable.Id_exFourStartDateText);
        exFourEndDateText = findComponentById(ResourceTable.Id_exFourEndDateText);
        exFourSaveButton = findComponentById(ResourceTable.Id_exFourSaveButton);
        legendLayout = findComponentById(ResourceTable.Id_legendLayout);

        close_fraction = findComponentById(ResourceTable.Id_f4_image_back);
        clear_selected = findComponentById(ResourceTable.Id_f4_text_clear);

        // Set the First day of week depending on Locale
        DayOfWeek[] daysOfWeek = DayExtensions.daysOfWeekFromLocale();
        int childCount = legendLayout.getChildCount();
        for (int i = 0; i < childCount; i++) {
            Text text = (Text) legendLayout.getComponentAt(i);
            text.setText(daysOfWeek[i].getDisplayName(TextStyle.SHORT, Locale.ENGLISH));
            text.setTextSize(15, Text.TextSizeType.FP);
            try {
                text.setTextColor(new Color(mContext.getResourceManager().getElement(ResourceTable.Color_example_4_grey).getColor()));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        YearMonth currentMonth = YearMonth.now();
        exFourCalendar.setup(currentMonth, currentMonth.plusMonths(12), daysOfWeek[0]);
        exFourCalendar.scrollToMonth(currentMonth);
        exFourCalendar.setDayBinder(new DayBinder<DayViewContainer>() {

            @Override
            public DayViewContainer create(Component component) {
                return new DayViewContainer(component);
            }

            @Override
            public void bind(DayViewContainer container, CalendarDay day) {
                try {
                    container.day = day;
                    Text textView = container.textView;
                    Component roundBgView = container.roundBgView;

                    textView.setText("");
                    textView.setBackground(null);
                    roundBgView.setVisibility(Component.INVISIBLE);
                    LocalDate startDate = Example4Fraction.this.startDate;
                    LocalDate endDate = Example4Fraction.this.endDate;
                    if (day.getOwner() == DayOwner.THIS_MONTH) {
                        textView.setText(String.valueOf(day.getDay()));
                        if (day.getDate().isBefore(today)) {
                            textView.setTextColor(new Color(mContext.getResourceManager().getElement(ResourceTable.Color_example_4_grey_past).getColor()));
                        } else {
                            if (day.getDate().equals(startDate) && null == endDate) {
                                textView.setTextColor(Color.WHITE);
                                roundBgView.setVisibility(Component.VISIBLE);
                                ShapeElement element = new ShapeElement(mContext, ResourceTable.Graphic_example_4_single_selected_bg);
                                roundBgView.setBackground(element);
                                int rgb = Color.rgb(11, 33, 97);
                                Color color = new Color(rgb);
                                exFourSaveButton.setTextColor(color);
                            } else if (day.getDate().equals(startDate)) {
                                textView.setTextColor(Color.WHITE);
                                textView.setBackground(getStartBackground());
                            } else if (startDate != null && endDate != null && (day.getDate().isAfter(startDate) && day.getDate().isBefore(endDate))) {
                                textView.setTextColor(Color.WHITE);
                                ShapeElement element = new ShapeElement(mContext, ResourceTable.Graphic_example_4_continuous_selected_bg_middle);
                                textView.setBackground(element);
                            } else if (day.getDate().equals(endDate)) {
                                textView.setTextColor(Color.WHITE);
                                textView.setBackground(getEndBackground());
                                exFourSaveButton.setTextColor(Color.WHITE);
                            } else if (day.getDate().equals(today)) {
                                textView.setTextColor(new Color(mContext.getResourceManager().getElement(ResourceTable.Color_example_4_grey).getColor()));
                                roundBgView.setVisibility(Component.VISIBLE);
                                ShapeElement element = new ShapeElement(mContext, ResourceTable.Graphic_example_4_today_bg);
                                roundBgView.setBackground(element);
                            } else {
                                textView.setTextColor(new Color(mContext.getResourceManager().getElement(ResourceTable.Color_example_4_grey).getColor()));
                            }
                        }
                    } else if (day.getOwner() == DayOwner.PREVIOUS_MONTH) {
                        if (startDate != null && endDate != null && isInDateBetween(day.getDate(), startDate, endDate)) {
                            ShapeElement element = new ShapeElement(mContext, ResourceTable.Graphic_example_4_continuous_selected_bg_middle);
                            textView.setBackground(element);
                        }

                    } else if (day.getOwner() == DayOwner.NEXT_MONTH) {
                        if (startDate != null && endDate != null && isOutDateBetween(day.getDate(), startDate, endDate)) {
                            ShapeElement element = new ShapeElement(mContext, ResourceTable.Graphic_example_4_continuous_selected_bg_middle);
                            textView.setBackground(element);
                        }
                    }


                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        exFourCalendar.setMonthHeaderBinder(new MonthHeaderFooterBinder<MonthViewContainer>() {
            @Override
            public MonthViewContainer create(Component component) {
                return new MonthViewContainer(component);
            }

            @Override
            public void bind(MonthViewContainer container, CalendarMonth month) {
                container.textView.setText(StringUtils.getFirstUpper(month.getYearMonth().getMonth().name().toLowerCase()) + " " + month.getYearMonth().getYear());
            }
        });
        exFourSaveButton.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                if (startDate != null && endDate != null) {
                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d MMMM yyyy");
                    String text = String.format("Selected: %s - %s", formatter.format(startDate), formatter.format(endDate));
                    toast(text);
                } else {
                    toast("No selection. Searching all Airbnb listings.");
                }
                backFraction();
            }
        });
        bindSummaryViews();

        initListener();
    }

    private void toast(String text) {
        ToastDialog toastDialog = new ToastDialog(mContext);
        Component dialogComponent = LayoutScatter.getInstance(mContext).parse(ResourceTable.Layout_example_4_dialog, null, false);
        Text dialogText = (Text) dialogComponent.findComponentById(ResourceTable.Id_dialog_text);
        dialogText.setText(text);
        toastDialog.setComponent(dialogComponent);
        DisplayAttributes attributes = DisplayManager.getInstance().getDefaultDisplay(mContext).get().getAttributes();

        toastDialog.setSize((int) (attributes.width * 0.9), (int) (attributes.height * 0.07));
        toastDialog.show();
    }

    private void initListener() {
        clear_selected.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                startDate = null;
                endDate = null;
                exFourCalendar.notifyCalendarChanged();
                bindSummaryViews();
            }
        });

        close_fraction.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                backFraction();
            }
        });
    }

    class DayViewContainer extends ViewContainer {
        CalendarDay day; // Will be set when this container is bound.
        Text textView;
        Component roundBgView;

        public DayViewContainer(Component component) {
            super(component);
            textView = (Text) component.findComponentById(ResourceTable.Id_exFourDayText);

            roundBgView = component.findComponentById(ResourceTable.Id_exFourRoundBgView);
            component.setClickedListener(new Component.ClickedListener() {
                @Override
                public void onClick(Component component) {
                    if (day.getOwner() == DayOwner.THIS_MONTH && (day.getDate().equals(today) || day.getDate().isAfter(today))) {
                        LocalDate date = day.getDate();
                        if (startDate != null) {
                            if (date.isBefore(startDate) || endDate != null) {
                                startDate = date;
                                endDate = null;
                            } else if (date != startDate) {
                                endDate = date;
                            }
                        } else {
                            startDate = date;
                        }
                        exFourCalendar.notifyCalendarChanged();
                        bindSummaryViews();
                    }
                }

            });

        }


    }

    private boolean isInDateBetween(LocalDate inDate, LocalDate startDate, LocalDate endDate) {
        if (LocalDateExtension.getInstance(startDate).getYearMonth().compareTo(LocalDateExtension.getInstance(endDate).getYearMonth()) == 0) {
            return false;
        }
        if (LocalDateExtension.getInstance(inDate).getYearMonth().compareTo(LocalDateExtension.getInstance(startDate).getYearMonth()) == 0) {
            return true;
        }
        if (LocalDateExtension.getInstance(inDate).getYearMonth().plusMonths(1).compareTo(LocalDateExtension.getInstance(endDate).getYearMonth()) == 0) {
            return true;
        }
        return inDate.isAfter(startDate) && inDate.isBefore(endDate);
    }

    private boolean isOutDateBetween(LocalDate outDate, LocalDate startDate, LocalDate endDate) {
        if (LocalDateExtension.getInstance(startDate).getYearMonth().compareTo(LocalDateExtension.getInstance(endDate).getYearMonth()) == 0) {
            return false;
        }
        if (LocalDateExtension.getInstance(outDate).getYearMonth().compareTo(LocalDateExtension.getInstance(endDate).getYearMonth()) == 0) {
            return true;
        }
        if (LocalDateExtension.getInstance(outDate).getYearMonth().plusMonths(1).compareTo(LocalDateExtension.getInstance(startDate).getYearMonth()) == 0) {
            return true;
        }
        return outDate.isAfter(startDate) && outDate.isBefore(endDate);
    }

    private void bindSummaryViews() {
        try {
            if (startDate != null) {
                exFourStartDateText.setText(headerDateFormatter.format(startDate));
                exFourStartDateText.setTextColor(new Color(mContext.getResourceManager().getElement(ResourceTable.Color_example_4_grey).getColor()));
            } else {
                String startDate = mContext.getResourceManager().getElement(ResourceTable.String_start_date).getString();
                exFourStartDateText.setText(startDate);
                exFourStartDateText.setTextColor(Color.GRAY);
            }

            if (endDate != null) {
                exFourEndDateText.setText(headerDateFormatter.format(endDate));
                exFourEndDateText.setTextColor(new Color(mContext.getResourceManager().getElement(ResourceTable.Color_example_4_grey).getColor()));
            } else {
                String endDate = mContext.getResourceManager().getElement(ResourceTable.String_end_date).getString();
                exFourEndDateText.setText(endDate);
                exFourEndDateText.setTextColor(Color.GRAY);
            }

            // Enable save button if a range is selected or no date is selected at all, Airbnb style.
            exFourSaveButton.setEnabled(endDate != null || (startDate == null && endDate == null));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    static class MonthViewContainer extends ViewContainer {
        Text textView;

        MonthViewContainer(Component component) {
            super(component);
            textView = (Text) component.findComponentById(ResourceTable.Id_exFourHeaderText);
        }
    }

    // We set the radius of the continuous selection background drawable dynamically
    // since the view size is `match parent` hence we cannot determine the appropriate
    // radius value which would equal half of the view's size beforehand.

    private ShapeElement getStartBackground() {
        float radius = (exFourCalendar.getWidth() / 7f) / 2f;
        float[] startRadiiArray = {topLeft, topLeft2, topRight, topRight2, bottomRight, bottomRight2, bottomLeft, bottomLeft2};
        startRadiiArray[0] = radius;
        startRadiiArray[1] = radius;
        startRadiiArray[6] = radius;
        startRadiiArray[7] = radius;
        startBackground.setCornerRadiiArray(startRadiiArray);
        return startBackground;
    }

    private ShapeElement getEndBackground() {
        float radius = (exFourCalendar.getWidth() / 7f) / 2f;
        float[] endRadiiArray = {topLeft, topLeft2, topRight, topRight2, bottomRight, bottomRight2, bottomLeft, bottomLeft2};
        endRadiiArray[2] = radius;
        endRadiiArray[3] = radius;
        endRadiiArray[4] = radius;
        endRadiiArray[5] = radius;
        endBackground.setCornerRadiiArray(endRadiiArray);
        return endBackground;
    }


}
